#include "precompiled.h"
#include "sntTextTest.h"

//
void sntTextTest::Test1()
{
/*
  dat::TVar V1,V2;
  dat::TVar_Stack Stack; Stack.Link(V1); Stack.Link(V2);

  V1 = "1"; V2 = 11; Stack.Push();
  V1 = "2"; V2 = 22; Stack.Push();
  V1 = "3"; V2 = 33; Stack.Push();

  svl::TString _V1; int _V2;

  Stack.Pop(); _V1 = V1; _V2 = V2;
  Stack.Pop(); _V1 = V1; _V2 = V2;
  Stack.Pop(); _V1 = V1; _V2 = V2;
*/

  struct TModule
  {
    snt::TRule  R1,R2;
    snt::TAlter A1,A2;

    svl::TVariant P1,P2;

    TModule
    (
      snt::text::TContext &Context
    )
    {
      P1 =  1;
      P2 = "2";

      snt::text::TSequence T(Context);
      snt::TFVoid F;
      snt::TReturn Return;

//Snt::TFVoid &Fxx = F(P1 << P2);
//svl::TString S=P1;
//Fxx.Execute();
//S=P1;

      R1.Local(P1,P2);
/**************************
      R1
      | T("func") & F(&Func) & F(&Func,P1,P2) & F(Copy(P1,P2))
      | T("1") & T("2") & T("3") & A1
      | A1 //& T("4") & A1 & R1
      | T("5") & Return //& T("qwerty")
      | A2 //& A2
      | R1
      | Return
      ;
      A1
      | T("1") & T("2") & T("3") & A1
      | A1 //& T("4") & A1 & R1
      | T("5")
      | A2 //& A2
      | R1
      ;
      A2
      | Return
      ;
****************************/      
    //T("") & R1;
    }
    //
    static void Func(snt::TParams &Params)
    {
      int P1 = Params.Pop();
      /*svl::TString P2 = */Params.Pop()="qw";
    }
  };

  snt::text::TContext context;
  TModule M(context);
  svl::TMessageModal(M.R1.GetGraphInfo(""));
}

//
void sntTextTest::Test2()
{
  char *S =
  "Param \r\n"
  "XXXXX = \"x1\" \r\n"
  "{\r\n"
  "  InDbTableName = \"Name\" \r\n"
  "  Type = \"Ref\" \r\n"
  "  {\r\n"
  "    ToFieldId = \"123\" \r\n"
  "  }\r\n" 
  "  T = \"t\" \r\n"
  "  T1 = \"t1\" \r\n"
  "}\r\n"
  "a =\"b\" "
  ;
  svl::TMem Mem; Mem.Add((BYTE*)S,lstrlen(S));
  snt::text::TContext Context; Context.Text() = Mem;

  svl::TString SOut; for (int N = 0; N < Context.Text().CountLines(); N++)
  {
    SOut << Context.Text().GetLine(N) << "\r\n";
  }
  svl::TMessageModal((svl::TString&)SOut);

  struct TRule : public snt::TRule
  {
    svl::TString SOut;

    snt::TRule    RLev;
    snt::TAlter   A1,A2,A3;
    svl::TVariant TagName,TagValue,This,Level;
    //
    TRule(snt::text::TContext &Context)
    {
      This  = this;
      Level = 0;

      snt::text::TIdent     Ident(Context);
      snt::TFVoid           F;
      snt::text::TSequence  Seq(Context);
      snt::text::TString    Str(Context);
      snt::text::TEndOfText EndOfText(Context);
      snt::TReturn          Return;

      // this -> RLev -> EndOfText ->
      this->Name("this")
      | RLev.New() & EndOfText.New() & Return.New()
      ;

//this->Or(RLev.And(EndOfText.And(Return)));

      //        1           2                3
      //        |<---------------------------|
      //        |           |--------------->|
      // RLev ->|-> Ident ->|-> '=' -> Str ->|->
      //        |-> '{' -> RLev -> '}' ----->|
      RLev.Name("RLev").Local(TagName)
      | A1.New()
      ;
      A1.Name("A1")
      | Ident.New(TagName) & F.New(FName,This,TagName) & A2.New()
      | Seq.New("{") & F.New(FL,This) & RLev.New() & Seq.New("}") & F.New(FR,This) & A3.New()
      ;
      A2.Name("A2")
      | Seq.New("=") & Str.New(TagValue) & F.New(FValue,This,TagValue) & A3.New()
      | A3.New()
      ;
      A3.Name("A3")
      | A1.New()
      | Return.New()
      ;
    }
    //
    static void FName(snt::TParams& Params)
    {
      TRule *This = dynamic_cast<TRule*>(Params.Pop().Pointer());
      This->SOut << NewLine(This) << Params.Pop().String();
    }
    static void FValue(snt::TParams& Params)
    {
      TRule *This = dynamic_cast<TRule*>(Params.Pop().Pointer());
      This->SOut << " = \"" << Params.Pop().String() << "\"";
    }
    static void FL(snt::TParams& Params)
    {
      TRule *This = dynamic_cast<TRule*>(Params.Pop().Pointer());
      This->SOut << NewLine(This) << "{";
      
      This->Level = This->Level.Integer() + 1;
    }
    static void FR(snt::TParams& Params)
    {
      TRule *This = dynamic_cast<TRule*>(Params.Pop().Pointer());
      This->Level = This->Level.Integer() - 1;
      This->SOut << NewLine(This) << "}";
    }
    static svl::TString NewLine(TRule* This)
    {
      svl::TString SLevel; SLevel.FillToLen(This->Level.Integer()*2,' '); 
      return svl::TString() << "\r\n" << SLevel;
    }
  }
  Rule(Context);

  svl::TMessageModal(Rule.GetGraphInfo(""));

  if (!Rule.Execute())
  {
    svl::TString SErr; SErr.FillToLen(Context.Errors().Get(0).Col,' ');
    SErr << "^" << Context.Errors().GetAsString();

    svl::TString SOut; for (int N = 0; N <= Context.Errors().Get(0).Line; N++)
    {
      SOut << Context.Text().GetLine(N) << "\r\n";
    }

    svl::TString S; S << SOut << SErr;
    svl::TMessageModal((svl::TString&)S);
  }
  else svl::TMessageModal
    (svl::TString() << S << "\r\n---------------------------\r\n" << Rule.SOut);
}

//
void sntTextTest::Test()
{
  struct TWindow : public svl::TWindow
  {    
    TWindow()
    {
      //Test1();
      Test2();
    }
  }
  Window;
}
